對於平常使用 UIKit 的我來說,這個專案結構對我來說有點認識,又有一點不認識😂。我認為在 SwiftUI 的開發旅程中,理解專案的基本結構是非常重要的一步。在今天的挑戰中,我們來認識 SwiftUI 專案的主要組成部分,並了解如何管理和使用這些資源。
在 Xcode 中,建立新的 SwiftUI 專案時,會自動產生一些檔案和資料夾。讓我們來好好看一下這些檔案是什麼用途吧!
HandyInventory_ironApp.swift 是一個 Swift 檔,由專案名 + App 組合而成。它定義 SwiftUI 專案的進入點,App 的啟動和生命週期都可以在這裡控制,它包含一個 App 協議的結構體(struct)。@main 標記代表 App 的進入點。body 定義 App 的初始場景,一般來說,這個場景會有一個主畫面,例如 ContentView。
import SwiftUI
@main
struct HandyInventoryApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
這段程式碼表示當 App 啟動時,會顯示 ContentView 的畫面。
ContentView.swift 是 SwiftUI 專案中主要實作 UI 的檔案。這邊的程式碼定義 SwiftUI 如何使用 View 協議來建構簡單靈活的界面。下面這段程式碼表示一個 Hello, world! 文字在 UI 上,並透過 Day2 提到的右邊的預覽視窗顯示。
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, world!")
.padding()
}
}
#Preview {
ContentView()
}
在這個範例中,我們看到 ContentView 是使用 struct 來定義的,而且並不是繼承 UIView ,而是實作一個名為 View 的 protocol ,這代表它符合 View 協議。這裡的 body 屬性是唯一且必須的部分,而我們可以發現 body 其實使用了一個很特別的型別 - some view 。在 Apple 提供的文件中有描述 some view 中的 some 所代表的是不透明的類型,也就是 Opaque Types ,發音念「歐配可」。
Opaque Types
所謂不透明的類型,可以把它視為 reverse 的泛型,為什麼呢?讓我們來看一下解釋:
Swift 中的函數有個很好的例子 max,它會傳回兩個輸入參數中的最大值,而這兩個參數的類型是未知的。
func max<T>(_ x: T, _ y: T) -> T where T: Comparable
這個函式規定兩個輸入參數必須具有相同的型別T,但我們並不知道 T 具體是哪種型別。然而,我們知道這些參數可以使用 > 運算子來比較。雖然在定義這個函式時,我們不清楚 T 是什麼,但在實際使用時,透過程式碼的上下文,我們可以推斷出輸入及輸出的具體類型。
與此相對應,當我們使用不透明類型時,我們不需要知道 View 內部的具體運作細節,這些細節只有編譯器會知道。換句話說,不透明類型可以返回一個特定的型別,但無需在定義時明確指定這個型別的細節。
有興趣的人可以參考下方的參考文獻,我覺得他們的舉例和講解都很不錯。第二個和第三個連結是使用健達出奇蛋來舉例 some view 的意思,第一個連結是一個 Youtube 教學 - ChaoCode,她實際使用 Playground 操作一遍,解釋什麼是 some view ,對我來說 ChaoCode 的解釋比較好懂XD。
參考資料:
Preview
在 SwiftUI 中,預覽功能(Preview)能夠即時顯示我們的 UI 變化,這是透過 #Preview 區塊來實現的。這段程式碼不會成為送審到 App Store 的一部分,但可以讓我們在 Xcode 中即時查看設計效果。
SwiftUI 之所以使用 Struct 來定義視圖,有幾個重要原因:
Persistence.swift 和 HandyInventory_iron.xcdatamodeld 都和 Core Data 相關,用來在本機上儲存資料,其背後操作的雖然仍是 SQLite,但它簡化資料庫的處理,讓不了解 SQL 指令的人也可以快速的為 App 建立並使用資料庫。
Assets.xcassets 資料夾用於管理 App 中的圖像和顏色資源。所有的 icon、圖片和顏色資源都可以放在這裡,並在 SwiftUI 中方便地引用。
SwiftUI 的即時預覽功能是它一個強大的功能,Preview Content 資料夾是用來放預覽時所需的內容,如測試資料(模擬 API 回傳的 Json)或圖片。使開發過程中,讓我們可以隨時看和調整 UI 的外觀和行為。
SwiftUI 和 UIKit 的專案架構真的不太一樣,我們以前所熟悉的某些東西都被置換成新的東西,還出現了與 UIView 不同的型別。不過這些新東西的出現,真的是簡化很多開發的步驟,使用起來也更方便、快速了呢!在撰寫這篇文章的時候,參考了蠻多不同的文章,為了避免各種大混雜,我直接按照章節將參考文獻放在裡面。那我們就明天再見囉!